#include "winmain.h"
#include "PGE2D.h"

#define KEY_DOWN(vk) ((GetAsyncKeyState(vk) & 0x80000)?1:0)

HINSTANCE g_hInstance;
HWND g_hWnd;
int g_nCmdShow;

PGE2D::Engine *g_engine = nullptr;

bool PGE2D::gameover = false;

LRESULT CALLBACK WndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
	switch ( msg )
	{
	case WM_KEYDOWN:
		if KEY_DOWN(VK_SPACE)
			g_engine->setFullScreen( !g_engine->getFullScreen() );
		if KEY_DOWN(VK_ESCAPE)
			PGE2D::gameover = true;
		break;
	case WM_QUIT:
	case WM_CLOSE:
	case WM_DESTROY:
		PGE2D::gameover = true;
		break;
	}
	return DefWindowProc( hWnd, msg, wParam, lParam );
}

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE, LPSTR lpCmdLine, int nCmdShow )
{
	
	WNDCLASSEX wc;
	MSG msg;
	RECT windowRect;
	DWORD dwStyle, dwExStyle;

	srand((unsigned int)time(nullptr));
	g_hInstance = hInstance;
	g_nCmdShow = nCmdShow;

	g_engine = new PGE2D::Engine();

	if ( !PGE2D::game_preload() ) {
		MessageBox(g_hWnd, "Error in game preload!", "Error", MB_ICONERROR );
		return 0;
	}

	char title[255];
	sprintf_s( title, sizeof(title), g_engine->p_appTitle.c_str() );
	
	windowRect.left = (long)0;
	windowRect.right = (long)g_engine->getScreenWidth();
	windowRect.top = (long)0;
	windowRect.bottom = (long)g_engine->getScreenHeight();

	//Registering the Window Class
	wc.cbSize = sizeof( WNDCLASSEX );
	wc.style = CS_HREDRAW | CS_VREDRAW;
	wc.lpfnWndProc = (WNDPROC)WndProc;
	wc.cbClsExtra = 0;
	wc.cbWndExtra = 0;
	wc.hInstance = hInstance;
	wc.hIcon = nullptr;
	wc.hCursor = LoadCursor( nullptr, IDC_ARROW );
	wc.hbrBackground = nullptr; 
	wc.lpszMenuName = nullptr;
	wc.lpszClassName = title;
	wc.hIconSm = nullptr;

	if( g_engine->getFullScreen() )
	{
		DEVMODE dm;
		memset( &dm, 0, sizeof(dm) );
		dm.dmSize = sizeof(dm);
		dm.dmPelsWidth = g_engine->getScreenWidth();
		dm.dmPelsHeight = g_engine->getScreenHeight();
		dm.dmBitsPerPel = g_engine->getColorDepth();
		dm.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;

		if( ChangeDisplaySettings( &dm, CDS_FULLSCREEN ) != DISP_CHANGE_SUCCESSFUL ) {
			MessageBox( nullptr, "Display mode failed", nullptr, MB_OK);
			g_engine->setFullScreen( false );
		}

		dwStyle = WS_POPUP;
		dwExStyle = WS_EX_APPWINDOW;
		ShowCursor( false );
	}
	else {
		dwStyle = WS_OVERLAPPEDWINDOW;
		dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
	}

	//adjust window to true requested size
	AdjustWindowRectEx( &windowRect, dwStyle, false, dwExStyle );

	if ( !RegisterClassEx( &wc ) ) {
		MessageBox( nullptr, "Window registration failed!", "Error!", 
			MB_ICONEXCLAMATION | MB_OK );
		return 0;
	}

	g_hWnd = CreateWindowEx( 0,
		title,
		title,
		dwStyle | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
		0, 0,
		windowRect.right - windowRect.left, 
		windowRect.bottom - windowRect.top,
		0, 
		0, 
		g_hInstance, 
		0);

	if ( !g_hWnd ) {
		MessageBox( g_hWnd, "Window Creation Failed!", "Error!", 
			MB_ICONEXCLAMATION | MB_OK );
		return 0;
	}

	ShowWindow( g_hWnd, g_nCmdShow );
	UpdateWindow( g_hWnd );

	g_engine->setWindowHandle( g_hWnd );
	if( !g_engine->Init(g_engine->getScreenWidth(), g_engine->getScreenHeight(), g_engine->getColorDepth(),
		g_engine->getFullScreen() ) )
	{
		MessageBox( g_hWnd, "Error with Engine::Init()", "Error", MB_OK );
		return 0;
	}

	while ( !PGE2D::gameover )
	{
		while( PeekMessage( &msg, nullptr, 0, 0, PM_REMOVE ) )
		{
			TranslateMessage( &msg );
			DispatchMessage( &msg );
		}
		g_engine->Update();
	}

	if( g_engine->getFullScreen() )
		ShowCursor( true );

	g_engine->Close();
	delete g_engine;

	return 0;
}